package com.myprocessing.box;

import java.util.ArrayList;

import com.myprocessing.gui.util.Color;
import com.myprocessing.gui.util.Font;
import processing.core.PConstants;

public class TextBox extends Box {

	private ArrayList<String> lines = new ArrayList<String>();
	public StringBuffer contents = new StringBuffer();
	protected Font font;
	protected float lineHeight;
	protected Color color = new Color();
	protected int textAlign = PConstants.LEFT;
	protected int textVAlign = PConstants.BASELINE;
	
	public enum Overflow { DISPLAY, CLIP, SCROLL };
	protected Overflow overflow;
	
	public Overflow getOverflow() {
		return overflow;
	}

	public void setOverflow(Overflow overflow) {
		this.overflow = overflow;
	}

	public TextBox() {
		super();
	}
	
	public TextBox(Font font, String contents, float lineHeight,
			int textAlign, int textVAlign) {
		super();
		this.contents = new StringBuffer(contents);
		this.font = font;
		this.lineHeight = lineHeight;
		this.textAlign = textAlign;
		this.textVAlign = textVAlign;
	}

	public int getTextAlign() {
		return textAlign;
	}

	public void setTextAlign(int textAlign) {
		this.textAlign = textAlign;
	}

	public void init() {
		super.init();
		if (font.getFont() == null) {
			font.init();
		}
		wrap();
	}
	
	public float getLineHeight() {
		return lineHeight;
	}

	public void setLineHeight(float lineHeight) {
		this.lineHeight = lineHeight;
	}

	public void setContents(String s) {
		contents = new StringBuffer(s);
		wrap();
	}
	
	public String getContents() {
		return contents.toString();
	}
	
	public void append(String s) {
		contents.append(s);
		wrap();
	}
		
	public void clear() {
		setContents(new String());
	}
	
	public void backspace() {
		if (contents.length() > 0) {
			contents.setLength(contents.length() - 1);
			wrap();
		}
	}
	
	protected void wrap() {

		if (pApplet == null)
			return;
		
		float wrapWidth = (float)size.getX();
		
		pApplet.textFont(font.getFont());
		
		// find the length of the longest word
		String c = new String(contents);
		String[] words = c.split(" ");
		float minWidth = 0;
		for (int i = 0; i < words.length; i++) {
			if (pApplet.textWidth(words[i]) > minWidth) {
				minWidth = pApplet.textWidth(words[i]);
			}
		}
		if (wrapWidth < minWidth) {
			wrapWidth = minWidth;
		}
		
		// reset lines
		lines = new ArrayList<String>();
		
		// break up into paragraphs
		String[] paras = c.split("\n");
		
		// wrap each paragraph
		for (String str : paras) {
			ArrayList<String> tmplines = new ArrayList<String>();
			int lastSpace = 0;
			int lastWrapIndex = 0;
	
			while (true) {
				int nextSpace = str.indexOf(" ", lastSpace);		
				if (nextSpace == -1) {
					nextSpace = str.length();
				}
			
				String sinceWrap = str.substring(lastWrapIndex, nextSpace);
				if (pApplet.textWidth(sinceWrap) > wrapWidth) {
					String wrapped = str.substring(lastWrapIndex, lastSpace);
					tmplines.add(wrapped);
					lastWrapIndex = lastSpace;
				}
				else if (nextSpace == str.length()) {
					tmplines.add(str.substring(lastWrapIndex, str.length()));
					break;
				}
				else {
					lastSpace = nextSpace + 1;
				}
			}
			
			lines.addAll(tmplines);
		}
		
	}

	public Font getFont() {
		return font;
	}

	public void setFont(Font font) {
		this.font = font;
	}
	
	// TODO: scrolling is broken if textVAlign isn't BASELINE
	public void drawBox() {
		
		pApplet.fill(color.getRed(), color.getGreen(), color.getBlue());
		pApplet.stroke(0);
		pApplet.textAlign(getTextAlign(), getTextVAlign());
		pApplet.textFont(font.getFont());
		
		float textHeight = lines.size() * lineHeight;
		
		float hPos = 0;
		if (overflow == Overflow.SCROLL && textHeight > size.getY()) {
			hPos = size.getY() - textHeight - lineHeight;
			hPos -= hPos % (int)lineHeight;
		}
		else {
			hPos = 0;
		}
		
		float xpos = 0;
		switch (getTextAlign()) {
			case PConstants.CENTER:
				xpos = size.getX() / 2f;
				break;
			case PConstants.RIGHT:
				xpos = size.getX();
				break;
		}
		
		for (int i = 0; i < lines.size(); i++) {
			String line = (String)lines.get(i);
			hPos += lineHeight;
			if (getOverflow() == Overflow.CLIP && hPos > size.getY())
				break;
			if (getOverflow() == Overflow.DISPLAY ||
					(hPos > 0 && hPos - lineHeight <= size.getY())) {
				pApplet.text(line, xpos, hPos);
			}
		}
	}

	public int getTextVAlign() {
		return textVAlign;
	}

	public void setTextVAlign(int textVAlign) {
		this.textVAlign = textVAlign;
	}

	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}
	
}
